<?php if(!defined('SPRITCH')) { exit(); }

// Spritch - An opensource PHP5 web framework

// Author: Luca Degasperi
// Licence: GNU GPL
// Site: http://www.spritch.org/

// Class: Output
// Summary: This class provides views rendering and caching
// Since: 0.9.1

class output extends spritch
{
	private $data = array();
	private $use_priority = false;
	private $direct = false;
	private $output = null;
	private $usecache = false;
	private $cache = false;
	private $cachetime = 60;
	
	public function __construct()
	{
		$this->set_header('Pragma: no-cache');
		$this->usecache = $this->configuration->get('cache',false);
		$this->profiler->log('output class started');
	}
	
	public function __set($key,$value)
	{
		$this->data[$key] = $value;
	}
	
	public function set_header($header)
	{
		header($header);
	}
	
	public function cache($cachetime = 60)
	{
		$this->cache = true;
		$this->cachetime = $cachetime;
	}
	
	public function set($key,$value)
	{
		$this->data[$key] = $value;
		return get('output');
	}
	
	public function get($key)
	{
		return $this->data[$key];
	}
		
	public function use_priority()
	{
		$this->use_priority = true;
	}
	
	public function direct()
	{
		$this->direct = true;
	}
		
	public function render($return = false)
	{
		$this->profiler->log('output rendering');
		if(!is_null($this->output))
			return;
			
		$buffer = ob_get_clean();	
		$this->profiler->log('output buffer: '.$buffer);
		
		if($this->direct)
		{
			ob_start();
			foreach($this->data as $value)
				echo $value;
			$this->output .= ob_get_clean();
		}
		else
		{		
			$helpers = spritch::singleton_array('helper');
			extract($helpers);
			$language = $this->language;
			
			$views = array();
			$views = spritch::singleton_array('view');
	
			foreach($views as $view_key => $view_value)
			{
				if(($this->use_priority and $view_value->has_priority()) or !$this->use_priority)
				{
					$path = $this->exists($view_key,'views');
					if(!empty($path))
					{					
						extract($view_value->get_data());
						extract($this->data);
						ob_start();
						include_once($path);
						$this->output .= ob_get_clean();					
					}
				}
			}			
		}
			
		if($return)
			return $this->output;
		echo $this->output;
		if($this->usecache and $this->cache)
			$this->write_cache();
	}
	
	private function write_cache()
	{
		$filename = md5($this->uri->routed_string());
		
		if(!$stream = fopen(CACHE.DS.$filename,'wb'))
		{
			$this->profiler->warning('Unable to write cache');
			return false;
		}
		
		$expire = time()+$this->cachetime;
		if (flock($stream,LOCK_EX))
		{
			fwrite($stream,$expire.'-time->'.$this->output);
			flock($stream,LOCK_UN);
		}
		else
		{
			$this->profiler->warning('Unable to lock a file');
			return false;
		}
		fclose($stream);
		chmod(CACHE.DS.$filename,0777);
		$this->profiler->log('cache written');
	}
	
	public function read_cache()
	{
		$filename = md5($this->uri->routed_string());
		if (!file_exists(CACHE.DS.$filename))
			return false;
		
		if(!$stream = fopen(CACHE.DS.$filename,'rb'))
		{
			$this->profiler->warning('unable to read cache');
			return false;
		}
		
		flock($stream,LOCK_SH);
		
		$output = "";
		if(filesize(CACHE.DS.$filename) > 0)
			$output = fread($stream,filesize(CACHE.DS.$filename));

		flock($stream,LOCK_UN);
		fclose($stream);
		
		if(!preg_match("/(\d+-time->)/",$output,$match))
			return false;
		
		if(time() >= trim(strtr($match['1'],'-time->','')))
		{ 		
			unlink(CACHE.DS.$filename);
			$this->profiler->log('cached file out of date, deleted');
			return false;
		}
		
		echo strtr($output,$match['0'],'');
		$this->profiler->log('cached file used');
		
		return true;
	}
	
	public function delete_cache()
	{
		$handle = opendir(CACHE);
		while($file = readdir($handle))
			if($file != ".." and $file != ".")
				unlink(CACHE.DS.$file);
		closedir($handle);
		$this->profiler->log('cache deleted');
	}
}
?>